package de.placidi.pressreview.textprocessing;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import de.placidi.pressreview.parsing.CountedWord;
import edu.stanford.nlp.ling.HasWord;
import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.process.Morphology;
import edu.stanford.nlp.tagger.maxent.MaxentTagger;

/**
 * Access point for the text processor. Contains functionality to investigate a text. 
 * 
 * @author Alexander Placidi
 *
 */
public class MyPOSTagger {

	private String taggerModel;
	private MaxentTagger tagger;
	
	public MyPOSTagger(String taggerModel) {
		this.taggerModel = taggerModel;
		tagger = new MaxentTagger(taggerModel);
	}

	/**
	 * Get the sentences from a text. 
	 * 
	 * @param text
	 * @return
	 * 		A list of sentences.
	 */
	public List<List<HasWord>> getSentences(String text) {
		StringReader r = new StringReader(text);
		List<List<HasWord>> sentences = MaxentTagger.tokenizeText(r);
		return sentences;
	}
	
	/**
	 * Processes all the words. Does tagging, filtering and lemmatization. 
	 * The method iterates a list of sentences and attaches an identifier to each single word. 
	 * Keeps only nouns and names and lemmatizes them. 
	 * Lemmatization means the reduction of a word to the base form. (authorities -> authority, for instance)
	 * 
	 * @param sentences
	 * @return
	 * 		A list of words.
	 */
	public List<List<String>> getTaggedAndFilteredSentences(List<List<HasWord>> sentences) {
		List<List<String>> tSentences = new ArrayList<List<String>>();
			
		for (List<HasWord> sentence : sentences) {
			ArrayList<TaggedWord> tSentence = tagger.tagSentence(sentence);
			List<String> words = new ArrayList<>();
			for (TaggedWord taggedWord : tSentence) {
				String tag = taggedWord.tag();
				if (tag.equals("NE") | tag.equals("NN") | tag.equals("NNP") | tag.equals("NNS")) {
					String lemmatizedWord = Morphology.lemmaStatic(taggedWord.value().toLowerCase(), tag, false);
					words.add(lemmatizedWord);
				}
			}
			tSentences.add(words);
			
		}	
		return tSentences;
	}
	
	/**
	 * Counts all the words and their neighbors in a sentence. Stores the information in hash maps. 
	 * 
	 * @param sentences
	 * @return
	 * 		A statistic object containing the data. 
	 */
	public StatisticWords getStats(List<List<String>> sentences) {
		
		HashMap<String, AdjacentWords> adjMap = new HashMap<>();
		HashMap<String, Integer> counted = new HashMap<String, Integer>();
		Integer maximum = new Integer(0);
		
		for (List<String> sentence : sentences) {
			for (String word : sentence) {
				if (adjMap.containsKey(word)) {
					adjMap.get(word).addNeighbor(sentence);
				} else {
					AdjacentWords adW = new AdjacentWords(word);
					adW.addNeighbor(sentence);
					adjMap.put(word, adW);
				}
				
				if (counted.containsKey(word)) {
					Integer i = counted.get(word) + 1;
					if (i > maximum) {
						maximum = i;
					}
					counted.put(word, i);
				} else {
					counted.put(word, 1);
				}
			}
		}
		
		List<CountedWord> cWords = new ArrayList<>();
		for (Entry<String, Integer> cWord : counted.entrySet()) {
			cWords.add(new CountedWord(cWord.getKey(), cWord.getValue()));
		}
		
		StatisticWords stats = new StatisticWords();
		Collections.sort(cWords);
		stats.setAdjMap(adjMap);
		stats.setcWords(cWords);
		stats.setMaxFrequency(maximum);
		
		return stats;
	}
		

	public String getTaggerModel() {
		return taggerModel;
	}

	public void setTaggerModel(String taggerModel) {
		this.taggerModel = taggerModel;
	}

}
